/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package entityBeans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;

/**
 *
 * @author h08125
 */
@Entity
@DiscriminatorValue("subject")
@NamedQueries({
    /* get the top level subject, the father of them all (all the subjects are its sons or subsons or sub sub ... */
    @NamedQuery(name = "subject.topLevelSubject", 
     query =    "SELECT u FROM SubjectEntity u"
                + " WHERE u.myFather IS NULL"
                + " ORDER BY u.id"),
    /* get a specific subject defined by his UUID */
    @NamedQuery(name = "subject.subjectByUuid", 
        query =     "SELECT u FROM SubjectEntity u"
                    + " WHERE u.uuid = :myUuid"
                     + " ORDER BY u.id"),
    /* get a specific subject defined by his ID */
    @NamedQuery(name = "subject.subjectById", 
        query =     "SELECT u FROM SubjectEntity u"
                    + " WHERE u.id = :myId"
                     + " ORDER BY u.id"),
})
public class SubjectEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Basic
    private String uuid; // just a hashed version of the ID (to prevent so dumb hack via http get variables
    @Basic
    private int depthLayer; // variable mostly used for display reasons in the subject administration
    @Basic
    private String title;
    @OneToMany (mappedBy="mySubject", fetch= FetchType.EAGER, cascade = CascadeType.ALL)
    private List<ThreadEntity> myThreads;
    @OneToMany (mappedBy="myFather", fetch= FetchType.EAGER, cascade = CascadeType.ALL)
    private List<SubjectEntity> mySons;
    @ManyToOne
    private SubjectEntity myFather;
    @ManyToOne
    private ModeratorEntity myModerator;
    
    public SubjectEntity() {
        this.myFather = null;
        this.myModerator = null;
        this.myThreads = (List) new ArrayList<SubjectEntity>();
        this.mySons = (List) new ArrayList<SubjectEntity>();
    }
    
    public int getDepthLayer() {
        return depthLayer;
    }
    public void setDepthLayer(int depthLayer) {
        this.depthLayer = depthLayer;
    }
    public String getUuid() {
        return uuid;
    }
    public void setUuid(String uuid) {
        this.uuid = uuid;
    }
    public ModeratorEntity getMyModerator() {
        return myModerator;
    }
    public void setMyModerator(ModeratorEntity myModerator) {
        this.myModerator = myModerator;
    }
    public List<ThreadEntity> getMyThreads() {
        return myThreads;
    }
    public void setMyThreads(List<ThreadEntity> myThreads) {
        this.myThreads = myThreads;
    }
    public List<SubjectEntity> getMySons() {
        return mySons;
    }
    public void setMySons(List<SubjectEntity> mySons) {
        this.mySons = mySons;
    }
    public SubjectEntity getMyFather() {
        return myFather;
    }
    public void setMyFather(SubjectEntity myFather) {
        this.myFather = myFather;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    /**
     * Determine the depthLayer of the subject by recursion
     * @param depth must be 0 when called
     * @return the newly computed depthLayer
     */
    private int recursivelyComputeDepthLayer(int depth) {
        if (this.myFather != null) { // if it has a father
            depth = this.myFather.recursivelyComputeDepthLayer(depth);
            depth++;
        }
        return depth;
    }
    /**
     * Can compute the currant depthLayer of the subject
     * @return the depthLayer
     */
    public int computeDepthLayer() {
        return this.recursivelyComputeDepthLayer(0);
    }
    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof SubjectEntity)) {
            return false;
        }
        SubjectEntity other = (SubjectEntity) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }
    @Override
    public String toString() {
        return "entityBeans.SubjectEntity[ id=" + id + " ]";
    }
    
    /**
     * display the values of the subject in the console
     * For debug reasons
     */
    public void showValues() {
        System.out.println("-------------DISPLAY SUBJECT VALUES ----------------------");
        System.out.println("id:"+this.getId());
        System.out.println("uuid:"+this.getUuid());
        System.out.println("depthLayer:"+this.getDepthLayer());
        System.out.println("title:"+this.getTitle());
        int test = 0;
        if (!this.getMySons().isEmpty()) {
            String str = "mySons:";
            for (int i = 0; i < this.getMySons().size();i++) {
                if (i > 0) {
                    str = str.concat("-");
                }
                str = str.concat(this.getMySons().get(i).getId().toString());
            }
            System.out.println(str);
        }
        else {
            System.out.println("mySons:EmptyList");
        }
        if (!this.getMyThreads().isEmpty()) {
            String str = "myThreads:";
            for (int i = 0; i < this.getMyThreads().size();i++) {
                if (i > 0) {
                    str = str.concat("-");
                }
                str = str.concat(this.getMyThreads().get(i).getId().toString());
            }
            System.out.println(str);
        }
        else {
            System.out.println("myThreads:EmptyList");
        }
        
        String strFather = "myFather:";
        strFather = (this.getMyFather() != null && this.getMyFather().getId() != null) ? strFather.concat(this.getMyFather().getId().toString()) : strFather.concat("null");
        System.out.println(strFather);
        
        String strModo = "myModerator:";
        strModo = (this.getMyModerator() != null && this.getMyModerator().getId() != null) ? strModo.concat(this.getMyModerator().getId().toString()) : strModo.concat("null");
        System.out.println(strModo);
        
        System.out.println("-------------END OF SUBJECT VALUES ----------------------");
    }
}
